import { buildMethodKey, getClassName, ParamsType } from "../common"
import { ReflectUtil } from "../di"

const decorate = (
  target: Object,
  methodName: string,
  paramIndex: number,
  paramId: string,
  paramType: ParamsType
) => {
  // 将参数按主键 routerKey 的位置 parameterIndex 填到 params 里面
  const methodKey = buildMethodKey(target, methodName)
  console.log(`@Param methodKey = ${methodKey}, target = ${getClassName(target)}, method = ${methodName}, paramIndex = ${paramIndex}, paramType = ${paramType}, paramId = ${paramId}`)
  const params = ReflectUtil.getParams(methodKey) || []
  params[paramIndex] = { paramIndex, paramId, paramType }
  ReflectUtil.defineParam(methodKey, params)
}

export const RequestParam = (paramId: string | any): ParameterDecorator => {
  return (target: Object, propertyKey: string, parameterIndex: number): any => {
    decorate(
      target,
      propertyKey,
      parameterIndex,
      paramId,
      ParamsType.query
    )
  }
}

export const RequestBody = (paramId?: string | any) => {
  return (target: Object, propertyKey: string, parameterIndex: number): any => {
    decorate(
      target,
      propertyKey,
      parameterIndex,
      paramId,
      ParamsType.body
    )
  }
}

export const PathVariable = (paramId: string | any) => {
  return (target: Object, propertyKey: string, parameterIndex: number): any => {
    decorate(
      target,
      propertyKey,
      parameterIndex,
      paramId,
      ParamsType.path
    )
  }
}

export const Response = () => {
  return (target: Object, propertyKey: string, parameterIndex: number) => {
    decorate(target, propertyKey, parameterIndex, "", ParamsType.response)
  }
}

export const Request = () => {
  return (target: Object, propertyKey: string, parameterIndex: number) => {
    decorate(target, propertyKey, parameterIndex, "", ParamsType.request)
  }
}

export const Header = (paramId: string) => {
  return (target: Object, propertyKey: string, parameterIndex: number) => {
    decorate(
      target,
      propertyKey,
      parameterIndex,
      paramId,
      ParamsType.header
    )
  }
}

export const Headers = () => {
  return (target: Object, propertyKey: string, parameterIndex: number) => {
    decorate(
      target,
      propertyKey,
      parameterIndex,
      "",
      ParamsType.header
    )
  }
}

export const Next = () => {
  return (target: Object, propertyKey: string, parameterIndex: number) => {
    decorate(target, propertyKey, parameterIndex, "", ParamsType.next)
  }
}

export const Err = () => {
  return (
    target: object | any,
    propertyKey: string,
    parameterIndex: number
  ) => {
    decorate(target, propertyKey, parameterIndex, "", ParamsType.error)
  }
}
